package ru.agiledev.akb.server;

import com.google.gwt.user.server.rpc.RemoteServiceServlet;
import org.hibernate.Session;
import org.hibernate.criterion.Restrictions;
import ru.agiledev.akb.client.RegistrationService;
import ru.agiledev.akb.server.domain.presentation.Author;
import ru.agiledev.akb.server.domain.presentation.History;
import ru.agiledev.akb.server.hibernate.HibernateUtil;
import ru.agiledev.akb.server.logic.UserManager;
import ru.agiledev.akb.server.util.HashUtils;
import ru.agiledev.akb.server.util.MailManager;
import ru.agiledev.akb.shared.User;
import ru.agiledev.akb.shared.exception.RegistrationException;
import ru.agiledev.akb.shared.exception.ResetPasswordException;

import javax.mail.MessagingException;
import java.security.NoSuchAlgorithmException;
import java.util.List;
import java.util.UUID;

/**
 * Created by a.kirillov
 * Date: 4/7/11 Time: 11:45 PM
 */

public class RegistrationServiceImpl extends RemoteServiceServlet implements RegistrationService {
    @Override
    public User registerUser(User user) throws RegistrationException, NoSuchAlgorithmException {

        Session session = HibernateUtil.getSessionFactory().openSession();

        List<Author> userList = session.createCriteria(Author.class).add(Restrictions.eq("login", user.getLogin())).list();


         if(userList.size()>0){
             session.close();
             throw new RegistrationException("Пользователь с таким именем уже существует!");
         }

        Author author = UserManager.createAuthor(user);
        History history = new History();
        author.setHistory(history);

        String password = user.getPassword();

        String encriptedPassword = "";
        encriptedPassword = HashUtils.createSHA256(password);


        author.setPassword(encriptedPassword);

        session.beginTransaction();
        session.save(history);
        session.save(author);

        session.getTransaction().commit();

        user = author.getUserView();

        session.close();
        return user;
    }

    @Override
    public void resetPassword(String email) throws ResetPasswordException {

        Session session = HibernateUtil.getSessionFactory().openSession();

        List<Author> userList = session.createCriteria(Author.class).add(Restrictions.or(
                Restrictions.eq("email", email),
                Restrictions.eq("login", email))
        ).list();


         if(userList.size()>0){
            Author author = userList.get(0);
             String mail = author.getEmail();
             String oldPwd = author.getPassword();
             String name = author.getFirstName()+" "+ author.getLastName();
             String newPwd = UUID.randomUUID().toString();

             try {
                 author.setPassword(HashUtils.createSHA256(newPwd));
             } catch (NoSuchAlgorithmException e) {
                 throw new ResetPasswordException("Ошибка при генерации пароля!");
             }
             session.beginTransaction();
             session.update(author);
             session.getTransaction().commit();



             try {
                 MailManager.postMail(name, newPwd, mail);
             } catch (MessagingException e) {
                 session.beginTransaction();
                 session.refresh(author);
                 author.setPassword(oldPwd);
                 session.update(author);
                 session.getTransaction().commit();
                 throw new ResetPasswordException("(MessagingException)\nОшибка при отправке сообщения. \nПароль не был изменен.");
             }

             session.close();

         } else throw new ResetPasswordException("Не существует пользователя с таким именем или адресом!");
    }

    @Override
    public User updateUser(User user) {
        Session session = HibernateUtil.getSessionFactory().openSession();
        User newUser = null;
        List<Author> userList = session.createCriteria(Author.class).add(Restrictions.eq("id", user.getId())
        ).list();

        if(userList.size()>0){
            Author author = userList.get(0);

            if(!author.getLogin().equals(user.getLogin())){
                author.setLogin(user.getLogin());
            }

            if(!author.getFirstName().equals(user.getFirstName())){
                author.setFirstName(user.getFirstName());
            }

            if(!author.getLastName().equals(user.getLastName())){
                author.setLastName(user.getLastName());
            }

            if(!author.getAffilation().equals(user.getAffilation())){
                author.setAffilation(user.getAffilation());
            }

            if(!author.getEmail().equals(user.getEmail())){
                author.setEmail(user.getEmail());
            }

            session.beginTransaction();
            session.update(author);

            session.getTransaction().commit();
            session.refresh(author);

            newUser = author.getUserView();

            session.close();
        }

        return newUser;
    }


    @Override
    public void updatePassword(User user, String oldPassword) throws RegistrationException {
        Session session = HibernateUtil.getSessionFactory().openSession();
        List<Author> userList = null;
        try {
            userList = session.createCriteria(Author.class).add(Restrictions.eq("id", user.getId()))
                    .add(Restrictions.eq("password", HashUtils.createSHA256(oldPassword))).list();
        } catch (NoSuchAlgorithmException e) {
            throw new RegistrationException("Ошибка при генерации пароля.");
        }
        if(userList.size()>0){

            Author author = userList.get(0);

            try {
                author.setPassword(HashUtils.createSHA256(user.getPassword()));
            } catch (NoSuchAlgorithmException e) {
                session.close();
                throw new RegistrationException("Ошибка при генерации пароля.");
            }

            session.beginTransaction();
            session.update(author);
            session.getTransaction().commit();
            session.close();


        }   else throw new RegistrationException("Пароль введен неверно");
    }
}